package cn.phantom.juctest;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;

class ClickNumber {
    public int number = 0;
    public synchronized void addSynchronized() {
        number++;
    }

    AtomicInteger atomicInteger = new AtomicInteger();
    public void add_AtomicInteger() {
        atomicInteger.incrementAndGet();
    }

    AtomicLong atomicLong = new AtomicLong();
    public void add_AtomicLong() {
        atomicLong.incrementAndGet();
    }

    LongAdder longAdder = new LongAdder();
    public void add_LongAdder() {
        longAdder.increment();
    }

    LongAccumulator longAccumulator = new LongAccumulator((x, y) -> x + y, 0);
    public void add_longAccumulator() {
        longAccumulator.accumulate(1);
    }
}

/**
 * 50个线程，每个线程点赞100w次，计算总点赞数
 */
public class LongAdderDemo02_ClickNumber {

    public static final int SIZE_THREAD = 50;
    public static final int _1W = 10000;

    public static void main(String[] args) throws InterruptedException {
        ClickNumber clickNumber = new ClickNumber();
        long startTime = 0;
        long endTime = 0;
        CountDownLatch countDownLatch1 = new CountDownLatch(SIZE_THREAD);
        CountDownLatch countDownLatch2 = new CountDownLatch(SIZE_THREAD);
        CountDownLatch countDownLatch3 = new CountDownLatch(SIZE_THREAD);
        CountDownLatch countDownLatch4 = new CountDownLatch(SIZE_THREAD);
        CountDownLatch countDownLatch5 = new CountDownLatch(SIZE_THREAD);

        startTime = System.currentTimeMillis();
        for (int i = 0; i < SIZE_THREAD; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < 100 * _1W ; j++) {
                        clickNumber.addSynchronized();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch1.countDown();
                }

            }, String.valueOf(i)).start();
        }
        countDownLatch1.await();
        endTime = System.currentTimeMillis();
        System.out.println(clickNumber.number + "----cost time: " + (endTime - startTime) + "毫秒" + "\t" + "addSynchronized");

        startTime = System.currentTimeMillis();
        for (int i = 0; i < SIZE_THREAD; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < 100 * _1W ; j++) {
                        clickNumber.add_AtomicInteger();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch2.countDown();
                }

            }, String.valueOf(i)).start();
        }
        countDownLatch2.await();
        endTime = System.currentTimeMillis();
        System.out.println(clickNumber.number + "----cost time: " + (endTime - startTime) + "毫秒" + "\t" + "add_AtomicInteger");


        startTime = System.currentTimeMillis();
        for (int i = 0; i < SIZE_THREAD; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < 100 * _1W ; j++) {
                        clickNumber.add_AtomicLong();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch3.countDown();
                }

            }, String.valueOf(i)).start();
        }
        countDownLatch3.await();
        endTime = System.currentTimeMillis();
        System.out.println(clickNumber.number + "----cost time: " + (endTime - startTime) + "毫秒" + "\t" + "add_AtomicLong");

        startTime = System.currentTimeMillis();
        for (int i = 0; i < SIZE_THREAD; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < 100 * _1W ; j++) {
                        clickNumber.add_LongAdder();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch4.countDown();
                }

            }, String.valueOf(i)).start();
        }
        countDownLatch4.await();
        endTime = System.currentTimeMillis();
        System.out.println(clickNumber.number + "----cost time: " + (endTime - startTime) + "毫秒" + "\t" + "add_LongAdder");

        startTime = System.currentTimeMillis();
        for (int i = 0; i < SIZE_THREAD; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < 100 * _1W ; j++) {
                        clickNumber.add_longAccumulator();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch5.countDown();
                }

            }, String.valueOf(i)).start();
        }
        countDownLatch5.await();
        endTime = System.currentTimeMillis();
        System.out.println(clickNumber.number + "----cost time: " + (endTime - startTime) + "毫秒" + "\t" + "add_longAccumulator");

        /*
        50000000----cost time: 2321毫秒	addSynchronized
        50000000----cost time: 442毫秒	add_AtomicInteger
        50000000----cost time: 443毫秒	add_AtomicLong
        50000000----cost time: 70毫秒	add_LongAdder
        50000000----cost time: 58毫秒	add_longAccumulator
         */
    }
}
